<!--
 * @Author: huang liang miao 1127255342@qq.com
 * @Date: 2024-09-02 10:40:10
 * @LastEditors: huang liang miao 1127255342@qq.com
 * @LastEditTime: 2024-12-19 10:23:27
 * @FilePath: \dcy-web\apps\admin\pages\user-management\components\RoleAuthority.vue
 * @Description: 角色权限
-->
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { menuListRoleReq, updateRoleReq, roleDetailReq } from "@/api/system/role/index"

const props = defineProps<{
  roleInfo: any
}>()

const treeData = ref()
const checkedList = ref<any>([]) // 已选择待提交的
const platformListids = ref([]) as any // 当前已选平台列表ids
const isOprional = ref(true) // 是否修改
const roleId = ref(props.roleInfo.id)
const treeDataLoading = ref(false)

const treeRef = ref<any>(null)
const defaultProps = <any>{
  children: 'children',
  label: (data) => data?.meta?.title,
  class: (_data, node) => {
    return `level-${node.level}`
  },
}

//  查询树
const { run: menuListRole, loading: treeLoading} = useRequest(menuListRoleReq, {
  // false 为自动执行
  manual: true,
	onSuccess: (data: any) => {
    treeDataLoading.value = true
    treeData.value = data
    roleDetail(roleId.value)
	}
})

// 查询已选
const { run: roleDetail } = useRequest(roleDetailReq, {
  // false 为自动执行
  manual: true,
	onSuccess: (res: any) => {
    if(res.menus) {
      checkedList.value = res.menus[0].menuIdList || []
      platformListids.value = res.menus[0].menuIdList || []
      removeId(treeData.value)
    } else{
      treeDataLoading.value = false
    }
	}
})
// 去除不是全选的父级id
function removeId(node) {
  node?.forEach(() => {
    node?.forEach((item) => {
      if(!item?.children?.every((v) => platformListids.value.includes(v.id)) && item?.children?.some(v => platformListids.value.includes(v.id))){
        platformListids.value = platformListids.value.filter(n => n !== item.id)
        checkedList.value = platformListids.value.filter(n => n !== item.id)
      }
      if(item?.children){
        return removeId(item?.children)
      }
      treeDataLoading.value = false
    })
  })
}
// 角色类型切换
watch(() => props.roleInfo, (v: any) => {
  if(v.id){
    roleId.value = v.id
    treeData.value = []
    checkedList.value = []
    platformListids.value = []
    menuListRole()
  }
}, {
  immediate: true, // 立即执行
})

// 保存
const { run: updateRole, loading } = useRequest(updateRoleReq, {
  manual: true,
  onSuccess: () => {
    ElMessage({
      message: '已保存',
      type: 'success',
    })
    treeData.value = []
    checkedList.value = []
    platformListids.value = []
    menuListRole()
  }
})

function saveMenu() {
  uploadData(treeData.value)
  updateRole({
    id: props.roleInfo?.id,
    name: props.roleInfo.name,
    menuIdList: uniqueArray(checkedList.value)
  })
}
// 去重
function uniqueArray(arr) {
  return [...new Set(arr)]
}

// 提交过滤
function uploadData(node) {
  node?.forEach((val) => {
    node?.forEach((item) => {
      if(!item?.children?.every((v) => checkedList.value.includes(v.id)) && item?.children?.some(v => checkedList.value.includes(v.id))){
        checkedList.value.push(item.id)
      }
    })
    if(val?.children){
      uploadData(val?.children)
    }
  })
}

// 判断是否已修改
function treeChanage(_node, data){
  checkedList.value = data.checkedKeys
  isOprional.value = arraysEqual(checkedList.value, platformListids.value)
}
function arraysEqual(arr1: any, arr2: any) {
  if (arr1.length !== arr2.length)
    return false

  const sortedArr1 = arr1.slice().sort()
  const sortedArr2 = arr2.slice().sort()

  for (let i = 0; i < sortedArr1.length; i++) {
    if (sortedArr1[i] !== sortedArr2[i])
      return false
  }
  return true
}

</script>

<template>
  <div class="w-full">
    <el-scrollbar v-loading="treeLoading || treeDataLoading" element-loading-text="加载中..." element-loading-background="rgba(255, 255, 255, 0.5)" :style="`height: calc(100vh - 276px); overflow: auto;`">
      <div class="pr-[16px]">
        <el-tree
          ref="treeRef"
          empty-text=""
          :default-checked-keys="checkedList"
          :props="defaultProps"
          :data="treeData"
          node-key="id"
          show-checkbox
          highlight-current
          default-expand-all
          :expand-on-click-node="false"
          @check="treeChanage"
        />
      </div>
    </el-scrollbar>
    <div  class="save">
      <el-button type="primary" :disabled="isOprional" :loading="loading" @click="saveMenu">保存</el-button>
    </div>
  </div>
</template>

<style lang="scss" scoped>
@import "@/assets/styles/variables.module.scss";

.save{
  @apply py-[20px] text-center relative z-10;
  box-shadow: 0 -2px 4px 0 #0000000f;
}
:deep(.el-tree-node__expand-icon){
  display: none!important;
}
:deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content),
:deep(.el-tree-node__content:hover){
  background: none !important;
}
:deep(.el-tree){
  .is-disabled.is-checked{
    .el-checkbox__inner{
      @apply: bg-[$--color-primary];
      &::after{
        @apply: border-color-white;
      }
    }
  }
  .el-tree-node__content{
    @apply: h-[32px];
    padding-left: 0!important;
  }
  .is-checked + .el-tree-node__label{
    @apply: text-[$--color-primary];
  }
  .el-tree-node__content,
  .el-tree-node__label{
    @apply: cursor-default;
  }
  .level-1{
    &>.el-tree-node__content{
      @apply: pb-[10px] border-b border-color-[#E5E6EB];
    }
    &>.el-tree-node__children{
      @apply: mb-[20px];
    }
  }
  .level-2{
    @apply: flex border border-t-0 border-color-[#E5E6EB];
    & >.el-tree-node__content{
      @apply: flex w-[200px] h-auto ml-[40px] py-[16px] items-center border-r border-color-[#E5E6EB];
    }
    & >.el-tree-node__children{
      @apply: flex-1 py-[8px] pl-[40px];
      & :not(:has(.el-tree-node .el-tree-node__children)){
        @apply inline-block vertical-middle;
      }
    }
    .level-3{
      @apply: py-[8px];
      & >.el-tree-node__children{
        @apply pl-[16px] ml-[8px] border-l border-color-[#E5E6EB] whitespace-break-spaces;
        & >.el-tree-node{
          @apply: inline-block;
        }
      }
    }
    .level-4{
      @apply: mr-[36px] py-[8px];
    }
  }
}
</style>
